<?php
class Pageley_Domain_Attribute_ManyToManyDecorator extends Pageley_Domain_Attribute_MultipleDecorator {
    private $relationTypes;
    
    public function __construct($attribute) {
        $validators = new Pageley_Util_ArrayMap();
        if(!($attribute instanceof Pageley_Domain_Attribute_Reference)) {
            throw new Pageley_Domain_RuntimeException("Only reference attributes are supported in many-to-many relationships.");
        }
        parent::__construct($attribute, $validators);
        $this->relationTypes = new Pageley_Util_ArrayMap();
    }

    public function isManyToMany() {
        return true;
    }
    
    public function getRelationType($referencingType) {
        $key = $referencingType->getFullName();
        $relationType = $this->relationTypes->get($key);
        if($relationType === null) {
            $relationType = $this->createRelationType($referencingType, $this->getDecoratedAttribute()->getType());
            $this->relationTypes->put($key, $relationType);
        }
        return $relationType;
    }
    
    private function createRelationType($referencingType, $referencedType) {
        $referencingTypeName = Pageley_Util_String::uncapitalize($referencingType->getName());
        $referencedTypeName = Pageley_Util_String::uncapitalize($referencedType->getName());
        $referencingTypeAttribute = new Pageley_Domain_Attribute_Reference($referencingTypeName, $referencingType);
        $referencedTypeAttribute = new Pageley_Domain_Attribute_Reference($referencedTypeName, $referencedType);
        $referencedTypeAttribute->setEager(true);
        $relationType = new Pageley_Domain_BasicType(
                $referencingType->getNamespace(),
                $referencingType->getName() . $referencedType->getName(),
                new Pageley_Util_ArrayMap(array(
                    $referencingTypeName => new Pageley_Domain_Attribute_RequiredDecorator($referencingTypeAttribute),
                    $referencedTypeName => new Pageley_Domain_Attribute_RequiredDecorator($referencedTypeAttribute)
                )));
        $configId = "type." . $referencingType->getFullName() . $referencedType->getName();
        return $relationType;
    }
    
    public function getConverter() {
        return null;
        // TODO: return new Pageley_Serializer_Converter_Default();
    }

    public function newProperty($entity) {
        return new Pageley_Mapper_LazyValueListProperty($entity, $this);
    }
    
    public function __toString() {
        return $this->getName() . "(many to many)";
    }             
}